package com.voe;

import com.voe.AudioDeviceModule.AudioLayer;
import com.voe.common.OutputParam;
import com.voe.common.ReturnValue;
import com.voe.common.StereoChannel;

/**This sub-API supports the following functionalities:<br/>
*<br/>
*- Audio device handling.<br/>
*- Device information.<br/>
*- CPU load monitoring.<br/>
*<br/>
*Usage example, omitting error checking:<br/>
*<br/>
*VoiceEngine voe = VoiceEngine.createInterface();<br/>
*VoEBase base = VoEBase.createInterface(voe);<br/>
*VoEHardware hardware  = VoEHardware.createInterface(voe);<br/>
*base.init();<br/>
*...<br/>
*int n_devices = hardware->getNumOfPlayoutDevices();<br/>
*...<br/>
*base.terminate();<br/>
*base.release();<br/>
*hardware.release();<br/>
*voe.release();<br/>
*/
public class VoEHardware {

	// [start] apis
	
	public static VoEHardware createInstance(VoiceEngine voiceEngine) {

		long p = GetInterface(voiceEngine._p);
		if(p != 0)
			return new VoEHardware(p);
		return null;
	}

	public void release() {
		if (_p != 0) {
			Release(_p);
		}
	}
	
	/** Gets the number of audio devices available for recording.
	 */
	public int getNumOfRecordingDevices(ReturnValue<Integer> devices) {
		OutputParam output = new OutputParam();
		int result = GetNumOfRecordingDevices(_p, output);
		if(result == 0) {
			devices.setValue((Integer) output.getObject()[0]);
		}
		return result;
	}

	/** Gets the number of audio devices available for playout.
	 */
	public int getNumOfPlayoutDevices(ReturnValue<Integer> devices) {
		OutputParam output = new OutputParam();
		int result = GetNumOfPlayoutDevices(_p, output);
		if(result == 0) {
			devices.setValue((Integer) output.getObject()[0]);
		}
		return result;
	}

	/** Gets the name of a specific recording device given by an |index|.<br/>
	 *  On Windows Vista/7, it also retrieves an additional unique ID<br/>
	 *  (GUID) for the recording device.
	 */
	public int getRecordingDeviceName(int index, ReturnValue<String> name, ReturnValue<String> guid) {
		OutputParam output = new OutputParam();
		int result = GetRecordingDeviceName(_p, index, output);
		if(result == 0) {
			name.setValue((String) output.getObject()[0]);
			guid.setValue((String) output.getObject()[1]);
		}
		return result;
	}

	/** Gets the name of a specific playout device given by an |index|.<br/>
	 *  On Windows Vista/7, it also retrieves an additional unique ID<br/>
	 *  (GUID) for the playout device.
	 */
	public int getPlayoutDeviceName(int index, ReturnValue<String> name, ReturnValue<String> guid) {
		OutputParam output = new OutputParam();
		int result = GetPlayoutDeviceName(_p, index, output);
		if(result == 0) {
			name.setValue((String) output.getObject()[0]);
			guid.setValue((String) output.getObject()[1]);
		}
		return result;
	}

	/** Checks if the sound card is available to be opened for recording.
	 */
	public int getRecordingDeviceStatus(ReturnValue<Boolean> isAvailable) {
		OutputParam output = new OutputParam();
		int result = GetRecordingDeviceStatus(_p, output);
		if(result == 0) {
			isAvailable.setValue((Boolean) output.getObject()[0]);
		}
		return result;
	}

	/** Checks if the sound card is available to be opened for playout.
	 */
	public int getPlayoutDeviceStatus(ReturnValue<Boolean> isAvailable) {
		OutputParam output = new OutputParam();
		int result = GetPlayoutDeviceStatus(_p, output);
		if(result == 0) {
			isAvailable.setValue((Boolean) output.getObject()[0]);
		}
		return result;
	}

	/** Sets the audio device used for recording.
	 */
	public int setRecordingDevice(int index, StereoChannel recordingChannel) {
		return SetRecordingDevice(_p, index, recordingChannel.getValue());
	}

	/** Sets the audio device used for recording.
	 */
	public int setRecordingDevice(int index) {
		return setRecordingDevice(index, StereoChannel.kStereoBoth);
	}

	/** Sets the audio device used for playout.
	 */
	public int setPlayoutDevice(int index) {
		return SetPlayoutDevice(_p, index);
	}

	/** Sets the type of audio device layer to use.
	 *  Don't allow a change if VoE is initialized.
	 */
	public int setAudioDeviceLayer(AudioLayer audioLayer) {
		return SetAudioDeviceLayer(_p, audioLayer.getValue());
	}

	/** Gets the currently used (active) audio device layer.
	 */
	public int getAudioDeviceLayer(ReturnValue<AudioLayer> audioLayer) {
		OutputParam output = new OutputParam();
		int result = GetAudioDeviceLayer(_p, output);
		if(result == 0) {
			audioLayer.setValue( AudioLayer.fromValue((Integer) output.getObject()[0]));
		}
		return result;
	}

	/** Gets the VoiceEngine's current CPU consumption in terms of the percent<br/>
	 *  of total CPU availability. [Windows only]
	 */
	public int getCPULoad(ReturnValue<Integer> loadPercent) {
		OutputParam output = new OutputParam();
		int result = GetCPULoad(_p, output);
		if(result == 0) {
			loadPercent.setValue((Integer) output.getObject()[0]);
		}
		return result;
	}

	/** Gets the computer's current CPU consumption in terms of the percent<br/>
	 *  of the total CPU availability. This method may fail a few times on<br/>
	 *  Windows because it needs a certain warm-up time before reporting the<br/>
	 *  result. You should check the return value and either try again or<br/>
	 *  give up when it fails.
	 */
	public int getSystemCPULoad(ReturnValue<Integer> loadPercent) {
		OutputParam output = new OutputParam();
		int result = GetSystemCPULoad(_p, output);
		if(result == 0) {
			loadPercent.setValue((Integer) output.getObject()[0]);
		}
		return result;
	}

	/** Not supported
	 */
	public int resetAudioDevice() {
		return ResetAudioDevice(_p);
	}

	/** Not supported
	 */
	public int audioDeviceControl(int par1, int par2, int par3) {
		return AudioDeviceControl(_p, par1, par2, par3);
	}

	/** Not supported
	 */
	public int setLoudspeakerStatus(boolean enable) {
		return SetLoudspeakerStatus(_p, enable);
	}

	/** Not supported
	 */
	public int getLoudspeakerStatus(ReturnValue<Boolean> enabled) {
		OutputParam output = new OutputParam();
		int result = GetPlayoutDeviceStatus(_p, output);
		if(result == 0) {
			enabled.setValue((Boolean) output.getObject()[0]);
		}
		return result;
	}

	/** Native sample rate controls (samples/sec)
	 */
	public int setRecordingSampleRate(int samples_per_sec) {
		return SetRecordingSampleRate(_p, samples_per_sec);
	}

	public int recordingSampleRate(ReturnValue<Integer> samples_per_sec) {
		OutputParam output = new OutputParam();
		int result = RecordingSampleRate(_p, output);
		if(result == 0) {
			samples_per_sec.setValue((Integer) output.getObject()[0]);
		}
		return result;
	}

	public int setPlayoutSampleRate(int samples_per_sec) {
		return SetPlayoutSampleRate(_p, samples_per_sec);
	}

	public int playoutSampleRate(ReturnValue<Integer> samples_per_sec) {
		OutputParam output = new OutputParam();
		int result = PlayoutSampleRate(_p, output);
		if(result == 0) {
			samples_per_sec.setValue((Integer) output.getObject()[0]);
		}
		return result;
	}

	/** *Experimental - not recommended for use.*<br/>
	 *  Enables the Windows Core Audio built-in AEC. Fails on other platforms.<br/>
	 *  <br/>
	 *  Currently incompatible with the standard VoE AEC and AGC; don't attempt<br/>
	 *  to enable them while this is active.<br/>
	 *  <br/>
	 *  Must be called before VoEBase::StartSend(). When enabled:<br/>
	 *  1. VoEBase::StartPlayout() must be called before VoEBase::StartSend().<br/>
	 *  2. VoEBase::StopSend() should be called before VoEBase::StopPlayout().<br/>
	 *  The reverse order may cause garbage audio to be rendered or the<br/>
	 *  capture side to halt until StopSend() is called.<br/>
	 *  <br/>
	 *  As a consequence, SetPlayoutDevice() should be used with caution<br/>
	 *  during a call. It will function, but may cause the above issues for<br/>
	 *  the duration it takes to complete. (In practice, it should complete<br/>
	 *  fast enough to avoid audible degradation).
	 */
	public int enableBuiltInAEC(boolean enable) {
		return EnableBuiltInAEC(_p, enable);
	}

	public boolean builtInAECIsEnabled() {
		return BuiltInAECIsEnabled(_p);
	}

	protected VoEHardware(long p) {
		_p = p;
	}

	protected long _p;

	// [end]
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	// [start] jni api

	// Factory for the VoEHardware sub-API. Increases an internal
	// reference counter if successful. Returns NULL if the API is not
	// supported or ifruction fails.
	private static native long GetInterface(long p_voiceEngine);

	// Releases the VoEHardware sub-API and decreases an internal
	// reference counter. Returns the new reference count. This value should
	// be zero for all sub-API:s before the VoiceEngine object can be safely
	// deleted.
	private static native int Release(long p_VoEHardware);

	// Gets the number of audio devices available for recording.
	private static native int GetNumOfRecordingDevices(long p_VoEHardware,
			OutputParam devices);

	// Gets the number of audio devices available for playout.
	private static native int GetNumOfPlayoutDevices(long p_VoEHardware,
			OutputParam devices);

	// Gets the name of a specific recording device given by an |index|.
	// On Windows Vista/7, it also retrieves an additional unique ID
	// (GUID) for the recording device.
	private static native int GetRecordingDeviceName(long p_VoEHardware,
			int index, OutputParam param);

	// Gets the name of a specific playout device given by an |index|.
	// On Windows Vista/7, it also retrieves an additional unique ID
	// (GUID) for the playout device.
	private static native int GetPlayoutDeviceName(long p_VoEHardware,
			int index, OutputParam param);

	// Checks if the sound card is available to be opened for recording.
	private static native int GetRecordingDeviceStatus(long p_VoEHardware,
			OutputParam isAvailable);

	// Checks if the sound card is available to be opened for playout.
	private static native int GetPlayoutDeviceStatus(long p_VoEHardware,
			OutputParam isAvailable);

	// Sets the audio device used for recording.
	private static native int SetRecordingDevice(long p_VoEHardware, int index,
			int recordingChannel);

	// Sets the audio device used for playout.
	private static native int SetPlayoutDevice(long p_VoEHardware, int index);

	// Sets the type of audio device layer to use.
	private static native int SetAudioDeviceLayer(long p_VoEHardware,
			int audioLayer);

	// Gets the currently used (active) audio device layer.
	private static native int GetAudioDeviceLayer(long p_VoEHardware,
			OutputParam audioLayer);

	// Gets the VoiceEngine's current CPU consumption in terms of the percent
	// of total CPU availability. [Windows only]
	private static native int GetCPULoad(long p_VoEHardware,
			OutputParam loadPercent);

	// Gets the computer's current CPU consumption in terms of the percent
	// of the total CPU availability. This method may fail a few times on
	// Windows because it needs a certain warm-up time before reporting the
	// result. You should check the return value and either try again or
	// give up when it fails.
	private static native int GetSystemCPULoad(long p_VoEHardware,
			OutputParam loadPercent);

	// Not supported
	private static native int ResetAudioDevice(long p_VoEHardware);

	// Not supported
	private static native int AudioDeviceControl(long p_VoEHardware, int par1,
			int par2, int par3);

	// Not supported
	private static native int SetLoudspeakerStatus(long p_VoEHardware,
			boolean enable);

	// Not supported
	private static native int GetLoudspeakerStatus(long p_VoEHardware,
			OutputParam enabled);

	// Native sample rate controls (samples/sec)
	private static native int SetRecordingSampleRate(long p_VoEHardware,
			int samples_per_sec);

	private static native int RecordingSampleRate(long p_VoEHardware,
			OutputParam samples_per_sec);

	private static native int SetPlayoutSampleRate(long p_VoEHardware,
			int samples_per_sec);

	private static native int PlayoutSampleRate(long p_VoEHardware,
			OutputParam samples_per_sec);

	// *Experimental - not recommended for use.*
	// Enables the Windows Core Audio built-in AEC. Fails on other platforms.
	//
	// Currently incompatible with the standard VoE AEC and AGC; don't attempt
	// to enable them while this is active.
	//
	// Must be called before VoEBase::StartSend(). When enabled:
	// 1. VoEBase::StartPlayout() must be called before VoEBase::StartSend().
	// 2. VoEBase::StopSend() should be called before VoEBase::StopPlayout().
	// The reverse order may cause garbage audio to be rendered or the
	// capture side to halt until StopSend() is called.
	//
	// As a consequence, SetPlayoutDevice() should be used with caution
	// during a call. It will function, but may cause the above issues for
	// the duration it takes to complete. (In practice, it should complete
	// fast enough to avoid audible degradation).
	private static native int EnableBuiltInAEC(long p_VoEHardware,
			boolean enable);

	private static native boolean BuiltInAECIsEnabled(long p_VoEHardware);

	// [end]
}
